package com.gymmsystem.GYMMSystem.service.impl;

import com.gymmsystem.GYMMSystem.dto.UserReservationDTO;
import com.gymmsystem.GYMMSystem.service.CourseService;
import com.gymmsystem.GYMMSystem.service.ReservationService;
import com.gymmsystem.GYMMSystem.entity.Reservation;
import com.gymmsystem.GYMMSystem.mapper.ReservationMapper;
import com.gymmsystem.GYMMSystem.service.UserMessageService;
import com.gymmsystem.GYMMSystem.service.UserService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.servlet.LocaleResolver;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
@RequiredArgsConstructor
@Slf4j
public class ReservationServiceImpl implements ReservationService {
    private final CourseService courseService;
    private final UserMessageService userMessageService;
    private final UserService userService;

    private final ReservationMapper reservationMapper;
    private final LocaleResolver localeResolver;

    // 获取用户的预约记录
    // 关联查询预约表、课程表、教练表
    // 返回包含课程名称、教练姓名等详细信息的预约列表
    // 使用场景：用户查看自己的预约历史
    @Override
    public List<Map<String, Object>> getUserReservations(Long userId) {
        return reservationMapper.findReservationsByUserId(userId);
    }


    // 获取教练的预约记录
    // 关联查询预约表、用户表、课程表
    // 返回包含用户昵称、课程名称等详细信息的预约列表
    // 使用场景：教练查看自己课程的预约情况
    @Override
    public List<Map<String, Object>> getCoachReservations(Long coachId) {
        return reservationMapper.findReservationsByCoachId(coachId);
    }

    // 根据预约ID获取预约详情
    // 通过主键查询单个预约记录
    // 使用场景：查看特定预约的详细信息
    @Override
    public Reservation getReservationById(Long reservationId) {
        return reservationMapper.selectById(reservationId);
    }

    // 业务逻辑：
    // 检查用户是否已预约该课程（防重复预约）
    // 检查课程是否还有空位
    // 插入预约记录
    // 增加课程当前人数
    // 使用场景：用户预约课程
    // 预约成功后添加一条消息（与消息中心模块关联）
    @Override
    @Transactional
    public boolean createReservation(Reservation reservation) {
        Long userId = reservation.getRUId();
        Long courseId = reservation.getRCId();

        // 1.检查用户等级是否可以预约该课程
        String courseGrade = courseService.getCourseGrade(courseId);
        if (!userService.canUserReserveCourse(userId, courseGrade)) {
            String userLevel = userService.getUserLevel(userId);
            String levelMessage = getUserLevelMessage(userLevel, courseGrade);
            throw new RuntimeException(levelMessage);
        }

        // 检查用户是否已经预约该课程（考虑状态）
        Reservation existingReservation = reservationMapper.findReservationByUserAndCourse(reservation.getRUId(), reservation.getRCId());
        if (existingReservation != null) {
            // 如果存在已取消的预约记录，则更新该记录
            if ("已取消".equals(existingReservation.getRStatus())) {
                // 重置预约记录状态和相关字段
                existingReservation.setRStatus("预约中");
                existingReservation.setRCreatedAt(LocalDateTime.now());
                existingReservation.setRCancelTime(null);
                existingReservation.setRCancelReason(null);
                existingReservation.setRNotes(reservation.getRNotes());
                
                // 更新预约记录
                boolean updateSuccess = reservationMapper.updateById(existingReservation) > 0;
                
                if (updateSuccess) {
                    courseService.incrementCourseCurrent(reservation.getRCId());
                    // 添加预约成功消息
                    userMessageService.insertBookingMessage(reservation.getRUId(),
                            "尊敬的"+userService.getUserById(reservation.getRUId()).getUNickname()+
                                    "，您预约的"+courseService.getCourseById(reservation.getRCId()).getCName()+"将于"+
                            courseService.getCourseById(reservation.getRCId()).getCTime()+"开始，请及时参与!",existingReservation.getRId());
                    return updateSuccess;
                }
                return false;
            } else {
                // 非已取消状态的预约存在，抛出异常
                throw new RuntimeException("您已经预约过该课程");
            }
        }

        // 2. 检查课程容量 - 使用CourseService的checkCourseCapacity方法
        if (!courseService.checkCourseCapacity(reservation.getRCId())) {
            throw new RuntimeException("课程已满，无法预约");
        }

        // 3. 设置预约状态为"预约中"
        reservation.setRStatus("预约中");
        reservation.setRCreatedAt(LocalDateTime.now());

        // 4. 插入预约记录
        boolean insertSuccess = reservationMapper.insert(reservation) > 0;

        // 5. 如果插入成功，增加课程当前人数 - 使用CourseService的方法
        if (insertSuccess) {
            courseService.incrementCourseCurrent(reservation.getRCId());
            // 添加预约成功消息
            userMessageService.insertBookingMessage(reservation.getRUId(),
                    "尊敬的"+userService.getUserById(reservation.getRUId()).getUNickname()+
                            "，您预约的"+courseService.getCourseById(reservation.getRCId()).getCName()+"将于"+
                    courseService.getCourseById(reservation.getRCId()).getCTime()+"开始，请及时参与!",reservation.getRId());
        }

        return insertSuccess;
    }

    /**
     * 根据用户等级和课程等级生成提示信息
     */
    private String getUserLevelMessage(String userLevel, String courseGrade) {
        switch (userLevel) {
            case "普通用户":
                return "普通用户无法预约课程，请充值获取积分提升用户等级";
            case "初级会员":
                if ("中级".equals(courseGrade)) {
                    return "初级会员无法预约中级课程，请充值获取积分提升至中级会员";
                } else if ("高级".equals(courseGrade)) {
                    return "初级会员无法预约高级课程，请充值获取积分提升至高级会员";
                }
                break;
            case "中级会员":
                if ("高级".equals(courseGrade)) {
                    return "中级会员无法预约高级课程，请充值获取积分提升至高级会员";
                }
                break;
        }
        return "当前用户等级不够，无法预约该课程，请充值获取积分提升用户等级";
    }

    // 更新预约信息
    // 修改预约的备注等信息
    // 自动更新updated_at时间戳
    // 使用场景：编辑预约信息
    @Override
    public boolean updateReservation(Reservation reservation) {
        return reservationMapper.updateById(reservation) > 0;
    }

    // 取消预约
    // 业务逻辑：
    // 将预约状态改为"已取消"
    // 记录取消时间和原因
    // 减少课程当前人数
    // 使用场景：用户取消课程预约
    // 预约成功后添加一条消息（与消息中心模块关联）
    @Override
    @Transactional
    public boolean cancelReservation(Long reservationId, String reason) {
        // 1. 检查预约是否存在
        Reservation reservation = reservationMapper.selectById(reservationId);
        if (reservation == null) {
            throw new RuntimeException("预约记录不存在");
        }

        // 2. 检查预约状态，避免重复取消
        if ("已取消".equals(reservation.getRStatus())) {
            throw new RuntimeException("该预约已取消，请勿重复操作");
        }

        // 3. 检查预约是否已完成，某些状态下可能不允许取消
        if ("已完成".equals(reservation.getRStatus())) {
            throw new RuntimeException("当前状态不允许取消预约");
        }

        // 4. 执行取消预约操作
        int updateResult = reservationMapper.cancelReservation(reservationId, reason);
        if (updateResult <= 0) {
            throw new RuntimeException("取消预约失败");
        }

        // 5. 减少课程当前人数
        try {
            courseService.decrementCourseCurrent(reservation.getRCId());
        } catch (Exception e) {
            log.error("减少课程人数失败，courseId: {}", reservation.getRCId(), e);
            throw new RuntimeException("取消预约过程中出现错误");
        }

        // 6. 获取最新的预约信息（包含取消时间）
        Reservation updatedReservation = reservationMapper.selectById(reservationId);

        // 7. 创建取消消息记录
        try {
            String userNickname = userService.getUserById(reservation.getRUId()).getUNickname();
            String courseName = courseService.getCourseById(reservation.getRCId()).getCName();
            String cancelTime = updatedReservation.getRCancelTime() != null ?
                    updatedReservation.getRCancelTime().toString() : "刚刚";

            userMessageService.insertCancelMessage(
                    reservation.getRUId(),
                    "尊敬的" + userNickname + "，您预约的" + courseName +
                            "课程于" + cancelTime + "取消成功",
                    reservation.getRId()
            );
        } catch (Exception e) {
            log.error("创建取消消息失败，reservationId: {}", reservationId, e);
            // 消息创建失败不影响主事务，但需要记录日志
        }

        return true;
    }

    // 作用：确认预约
    // 将预约状态从"预约中"改为"已确认"
    // 使用场景：管理员确认用户的预约
    @Override
    public boolean confirmReservation(Long reservationId) {
        return reservationMapper.updateReservationStatus(reservationId, "已确认") > 0;
    }

    // 作用：完成预约
    // 将预约状态改为"已完成"
    // 使用场景：课程结束后标记预约完成
    @Override
    public boolean completeReservation(Long reservationId) {
        return reservationMapper.updateReservationStatus(reservationId, "已完成") > 0;
    }

    // 作用：检查用户是否已预约某课程
    // 防止用户重复预约同一课程
    // 使用场景：预约前的重复性检查
    @Override
    public boolean checkUserCourseReservation(Long userId, Long courseId) {
        return reservationMapper.checkUserCourseReservation(userId, courseId) > 0;
    }

    // 作用：获取课程的活跃预约数量
    // 统计状态为"预约中"和"已确认"的预约数量
    // 使用场景：课程人数统计、容量检查
    @Override
    public int getActiveReservationsCount(Long courseId) {
        return reservationMapper.countActiveReservationsByCourse(courseId);
    }
    
    @Override
    public Long countActiveReservations() {
        return reservationMapper.countActiveReservations();
    }
    
    @Override
    public Long countPendingReservations() {
        return reservationMapper.countPendingReservations();
    }
    
    @Override
    @Transactional
    public Integer confirmAllPendingReservations() {
        return reservationMapper.confirmAllPendingReservations();
    }

    @Override
    public List<Map<String, Object>> getAllActiveReservations() {
        return reservationMapper.findAllActiveReservations();
    }

    @Override
    public List<Map<String, Object>> getCancelledReservations() {
        return reservationMapper.findAllCancelledReservations();
    }

    @Override
    public Map<String, Object> getActiveReservationsByPage(Integer page, Integer size) {
        // 参数校验
        if (page == null || page < 1) {
            page = 1;
        }
        if (size == null || size < 1 || size > 100) {
            size = 10;
        }
        
        // 计算偏移量
        Integer offset = (page - 1) * size;
        
        // 查询数据
        List<Map<String, Object>> data = reservationMapper.findActiveReservationsByPage(size, offset);
        Long total = reservationMapper.countActiveReservations();
        
        // 构建返回结果
        Map<String, Object> result = new HashMap<>();
        result.put("data", data);
        result.put("total", total);
        result.put("page", page);
        result.put("size", size);
        result.put("totalPages", total % size == 0 ? total / size : total / size + 1);
        
        return result;
    }

    @Override
    public Map<String, Object> getCancelledReservationsByPage(Integer page, Integer size) {
        // 参数校验
        if (page == null || page < 1) {
            page = 1;
        }
        if (size == null || size < 1 || size > 100) {
            size = 10;
        }
        
        // 计算偏移量
        Integer offset = (page - 1) * size;
        
        // 查询数据
        List<Map<String, Object>> data = reservationMapper.findCancelledReservationsByPage(size, offset);
        Long total = reservationMapper.countCancelledReservations();
        
        // 构建返回结果
        Map<String, Object> result = new HashMap<>();
        result.put("data", data);
        result.put("total", total);
        result.put("page", page);
        result.put("size", size);
        result.put("totalPages", total % size == 0 ? total / size : total / size + 1);
        
        return result;
    }

    // 获取用户预约DTO列表
    // 返回结构化的用户预约信息，包含所需的所有字段
    // 使用场景：个人中心展示预约详情
    @Override
    public List<UserReservationDTO> getUserReservationsDTO(Long userId) {
        return reservationMapper.findUserReservationsWithDTO(userId);
    }
}